#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author: ystlong
# @Date:   2019-07-07 01:23:40
# @Last Modified by:   ystlong
# @Last Modified time: 2019-07-07 03:57:04

import os, sys
import sqlite3

def list_files(root_dir, file_handle):
	# os.walk 将会遍历root_dir以及其所有的子目录
	for root, dirs, files in os.walk(root_dir, topdown=False):
		# for dir_name in dirs:
		# 	print("dir: %s"%(os.path.join(root, dir_name)))
		for file_name in files:
			file_handle(os.path.join(root, file_name), file_name)
		# print(root, dirs)

# def test_file_handle(file_path, file_name):
# 	print("file: %s"%(file_path))
# list_files(".", test_file_handle)

class DirIndex(object):
	"""
	pre_url rel_path file_name file_ext file_size file_date
	"""

	def __init__(self, database_file, prefix_uri='', debug=False):
		super(DirIndex, self).__init__()
		self.debug = debug
		# self.prefix_uri = prefix_uri
		self.db_file = database_file
		# self.db_file = os.path.realpath(__file__) + ".db"
		# # self.db_file = "gen_file_index.db"
		# self.db_file = ":memory:"

		self.conn = sqlite3.connect(self.db_file)
		self._init_database()

	def debug_print(self, *msg):
		if self.debug:
			print(*msg)

	def _database_execute(self, sql, args=()):
		self.debug_print(sql, args)
		res = self.conn.execute(sql, args)
		self.conn.commit()
		return res

	def _init_database(self):
		# res = self._database_execute("drop table if exists files")
		res = self._database_execute("""
			create table if not exists files(
			file_path text PRIMARY KEY not null,
			file_name text not null,
			file_ext text not null,
			size int)
		""")

	def _insert_one_item(self, file_path, file_name, file_ext, size, date_str='', insert_count=0, insert=True):
		if insert:
			sql = """insert or replace into files (file_path, file_name, file_ext, size) values(?,?,?,?)"""
			args = (file_path, file_name, file_ext, size)
			res = self.conn.execute(sql, args)
		if insert_count / 10000 == 0:
			self.conn.commit()

	def generate_database(self, root_path):
		insert_count = 0
		rel_root_path = ""
		def _insert_file_handle(file_path, file_name):
			nonlocal insert_count
			insert_count += 1
			rel_file_path = file_path.replace(root_path, "").lstrip("/.")
			file_ext = os.path.splitext(rel_file_path)[-1].strip(".")
			self.debug_print("insert file: ", file_path, rel_file_path)
			self._insert_one_item(rel_file_path, file_name, file_ext, 0, insert_count=insert_count)
		list_files(root_path, _insert_file_handle)
		# commit last item
		self._insert_one_item(None, None, None, 0, insert_count=0, insert=False)

	def search_file(self, query_str, word=False, page_size=0, page_no=0):
		sql = """select file_path, file_name, file_ext, size from files where file_path like ?"""
		q = "%%%s%%"%("%".join(list(query_str)))
		if word:
			q = "%%%s%%"%("%".join(query_str.split()))
		params = [q]
		count_sql = """select count(1) from files where file_path like ?"""
		total_count = self._database_execute(count_sql, params).fetchone()[0]
		if page_size > 0 and page_no > 0:
			sql += " limit ?,?"
			params.append(page_size*(page_no-1))
			params.append(page_size)
		res = self._database_execute(sql, params).fetchall()
		return (total_count, res)

class DirIndexHtml(object):
	"""docstring for DirIndexHtml"""
	def __init__(self):
		super(DirIndexHtml, self).__init__()

		self.html_tpl = """
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>search list</title>
</head>
<body>
<form action="">
    <input type="text" name="name" value="{query_str}">
    <br />
    <input type="checkbox" name="word" value="" {word_checked} /> query by word
</form>
<hr />
<table>
    <tr><th>pp</th><th>ext</th><th>file_name</th><th>size</th></tr>
	{rows}
</table>
<div>
    <!-- page str -->
    <span>total: {total_count}</span>
    <span><a href="?page=1&page_size={page_size}"><<</a></span>
    {pages}
    <span><a href="?page={last_page}&page_size={page_size}">>></a></span>
</div>
</body>
</html>
		"""

		self.row_tpl = """
			<tr>
				<td><a href="{path}/..">..</a></td>
				<td>{ext}</td>
				<td><a href="{path}">{name}</a></td>
				<td>{size}</td>
			</tr> 
		"""
		
		self.page_tpl = """
		span><a href="?page={page}&page_size={page_size}">{page}</a></span>
		"""

	def format_search(self, results, query_str, page_size, page_no, word):
		total_count = results[0]
		items = results[1]
		row_item_html = []
		pages_html = []
		total_pages = 1

		for item in items:
			tr = self.row_tpl.format(path=item[0], name=item[1], ext=item[2], size=item[3])
			row_item_html.append(tr)
		
		if page_size > 0:
			total_pages = total_count / page_size
			if total_count % page_size != 0:
				total_pages += 1
			# 显示当前页前后3page,共7page
			start_page = page_no - 3 if page_no > 3 else 1
			end_page = start_page + 7
			if end_page > total_pages:
				end_page = total_pages
			for i in xrange(start_page, end_page+1):
				# print(start_page, end_page, i)
				tt = self.page_tpl.format(page=i, page_size=page_size)
				pages_html.append(tt)

		content = self.html_tpl.format(
			query_str=query_str,
			word_checked="checked" if word else "",
			rows="".join(row_item_html),
			total_count=total_count,
			page_size=page_size,
			last_page=total_pages,
			pages="".join(pages_html)
		)
		return content

def test():
	query_name = "filex"
	page_size = -1
	page_no = 0
	word = True

	dinx = DirIndex(":memory:", debug=False)
	dinx.generate_database("/home/long/work/sample")
	res = dinx.search_file(query_name, word=word, page_size=page_size, page_no=page_no)
	# print(res)
	dih = DirIndexHtml()
	html_res = dih.format_search(res, query_name, page_size, page_no, word)
	print(html_res)
	# print(dih.format_search(res), query_name)

def get_db_file():
	db_file = os.path.realpath(__file__) + ".db"
	root_dir = os.path.dirname(os.path.realpath(__file__))
	return db_file, root_dir

def cgi():
	# CGI处理模块
	import cgi, cgitb 
	# 创建 FieldStorage 的实例化
	form = cgi.FieldStorage() 
	# 获取数据
	query_name = form.getvalue('name')
	page_size = form.getvalue("page_size")
	page_no = form.getvalue("page")
	word = form.getvalue("word")

	db_file, root_dir = get_db_file()

	dinx = DirIndex(db_file, debug=False)
	res = dinx.search_file(query_name, word=word, page_size=page_size, page_no=page_no)
	dih = DirIndexHtml()
	html_res = dih.format_search(res, query_name, page_size, page_no, word)

	print("Content-type:text/html\n\n\n")
	print(html_res)
	

def scan():
	db_file, root_dir = get_db_file()
	dinx = DirIndex(db_file, debug=False)
	dinx.generate_database(root_dir)
	
def query(query_str):
	db_file, root_dir = get_db_file()
	dinx = DirIndex(db_file, debug=False)
	total_count, itmes = dinx.search_file(query_str)
	# print(total_count)
	print("total count: %d\n"%(total_count))
	for r in itmes:
		print(r[0])

# def flask_web():
# 	import flask
# 	app = flask.Flask(__name__)
# 	@app.route('/')
# 	def search():
# 		query_name = flask.request.args.get("name", "")
# 		query_name = flask.request.form.get("name", query_name)
# 		if query_name == None:
# 			query_name = ""

# 		di = DirIndex(".")
# 		res = di.search_file(query_name)
# 		dih = DirIndexHtml()
# 		res = dih.format_search(res, query_name)
# 		return res
# 	# print(sys.argv)
# 	if len(sys.argv) == 3:
# 		addr, port = sys.argv[2].split(":")
# 		# print(addr, port)
# 		app.run(host=addr, port=int(port))
# 	else:
# 		app.run()

def help():
	# usage_str = """
	# usage: 
	# 	{boot_name} flask [addr:port]
	# 	{boot_name} scan scan_relative_root_path
	# 	{boot_name} query query_str
	# """.format(boot_name=sys.argv[0])
	usage_str = """
	usage: 
		{boot_name} flask [addr:port]
		{boot_name} scan
		{boot_name} query query_str
	""".format(boot_name=sys.argv[0])
	print(usage_str)

if __name__ == '__main__':
	# test()
	try:
		if sys.argv[1] == "flask":
			flask_web()
		elif sys.argv[1] == "scan":
			# scan(sys.argv[2])
			scan()
		elif sys.argv[1] == "query":
			query(sys.argv[2])
	except IndexError:
		help()
		raise
	except:
		raise
	
